package cn.edu.tju.elm.controller;

import cn.edu.tju.core.model.HttpResult;
import cn.edu.tju.core.model.ResultCodeEnum;
import cn.edu.tju.core.model.User;
import cn.edu.tju.core.security.PermissionUtils;
import cn.edu.tju.core.security.SecurityUtils;
import cn.edu.tju.core.security.service.UserService;
import cn.edu.tju.elm.dto.ComplainCreateDTO;
import cn.edu.tju.elm.dto.ComplainResponseDTO;
import cn.edu.tju.elm.dto.ComplainUpdateDTO;
import cn.edu.tju.elm.mapper.ComplainMapper;
import cn.edu.tju.elm.model.Business;
import cn.edu.tju.elm.model.Complain;
import cn.edu.tju.elm.model.Order;
import cn.edu.tju.elm.service.BusinessService;
import cn.edu.tju.elm.service.ComplainService;
import cn.edu.tju.elm.service.OrderService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * ClassName: ComplainController
 * Package: cn.edu.tju.elm.controller
 * Description: 投诉管理控制器
 *
 * @Author System
 * @Create 2025/10/31
 * @Version 1.0
 */
@RestController
@RequestMapping("/api/complains")
@Tag(name = "投诉管理", description = "提供对订单投诉的增删改查功能")
public class ComplainController {

    @Autowired
    private ComplainService complainService;

    @Autowired
    private UserService userService;

    @Autowired
    private OrderService orderService;

    @Autowired
    private BusinessService businessService;

    @Autowired
    private ComplainMapper complainMapper;

    @Autowired
    private PermissionUtils permissionUtils;

    /**
     * 用户提交投诉
     */
    @PostMapping("")
    @PreAuthorize("hasAnyAuthority('ADMIN','USER')")
    @Operation(summary = "提交投诉", description = "用户为订单提交投诉，一个订单只能投诉一次")
    public HttpResult<ComplainResponseDTO> addComplain(@Valid @RequestBody ComplainCreateDTO complainCreateDTO) {
        try {
            // 获取当前用户
            User currentUser = userService.getUserWithAuthorities()
                    .orElseThrow(() -> new IllegalStateException("无法获取当前用户信息"));

            // 获取订单信息
            Order order = orderService.getOrderById(complainCreateDTO.getOrderId())
                    .orElseThrow(() -> new IllegalArgumentException("订单不存在"));

            // 验证订单是否属于当前用户
            if (!order.getCustomer().getId().equals(currentUser.getId())) {
                return HttpResult.failure(ResultCodeEnum.BAD_REQUEST, "无权对此订单提交投诉");
            }

            // 创建投诉
            Complain complain = complainMapper.createDtoToComplain(complainCreateDTO);
            complain.setCustomer(currentUser);
            complain.setOrder(order);
            complain.setDeleted(false);
            complain.setBusiness(order.getBusiness());
            complain.setCreateTime(LocalDateTime.now());
            complain.setUpdateTime(LocalDateTime.now());

            Complain savedComplain = complainService.addComplain(complain);
            ComplainResponseDTO responseDTO = complainMapper.complainToResponseDTO(savedComplain);

            return HttpResult.success(responseDTO);
        } catch (IllegalArgumentException e) {
            return HttpResult.failure(ResultCodeEnum.BAD_REQUEST, e.getMessage());
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "提交投诉失败：" + e.getMessage());
        }
    }

    /**
     * 根据ID查询投诉详情
     */
    @GetMapping("/{id}")
    @PreAuthorize("hasAnyAuthority('ADMIN','USER','BUSINESS')")
    @Operation(summary = "根据ID查询投诉", description = "管理员、投诉用户或被投诉商家可查看")
    public HttpResult<ComplainResponseDTO> getComplainById(@PathVariable Long id) {
        Optional<Complain> complainOpt = complainService.getComplainById(id);
        if (complainOpt.isEmpty()) {
            return HttpResult.failure(ResultCodeEnum.NOT_FOUND, "投诉不存在");
        }

        Complain complain = complainOpt.get();
        
        // 权限检查：管理员可以访问所有，用户只能访问自己的投诉，商家只能访问针对自己的投诉
        if (!permissionUtils.isAdmin() && 
            !permissionUtils.canAccessComplainData(complain.getCustomer().getId()) &&
            !permissionUtils.canAccessBusinessData(complain.getBusiness().getBusinessOwner().getId())) {
            return HttpResult.failure(ResultCodeEnum.BAD_REQUEST, "无权访问此投诉信息");
        }

        ComplainResponseDTO responseDTO = complainMapper.complainToResponseDTO(complain);
        return HttpResult.success(responseDTO);
    }

    /**
     * 根据订单ID查询投诉
     */
    @GetMapping("/order/{orderId}")
    @PreAuthorize("hasAnyAuthority('ADMIN','USER','BUSINESS')")
    @Operation(summary = "根据订单ID查询投诉")
    public HttpResult<ComplainResponseDTO> getComplainByOrderId(@PathVariable Long orderId) {
        Optional<Complain> complainOpt = complainService.getComplainByOrderId(orderId);
        if (complainOpt.isEmpty()) {
            return HttpResult.failure(ResultCodeEnum.NOT_FOUND, "该订单暂无投诉信息");
        }

        Complain complain = complainOpt.get();
        
        // 权限检查：管理员可以访问所有，用户只能访问自己订单的投诉，商家只能访问针对自己的投诉
        if (!permissionUtils.isAdmin() && 
            !permissionUtils.canAccessComplainData(complain.getCustomer().getId()) &&
            !permissionUtils.canAccessBusinessData(complain.getBusiness().getBusinessOwner().getId())) {
            return HttpResult.failure(ResultCodeEnum.BAD_REQUEST, "无权访问此投诉信息");
        }

        ComplainResponseDTO responseDTO = complainMapper.complainToResponseDTO(complain);
        return HttpResult.success(responseDTO);
    }

    /**
     * 查询当前用户的所有投诉
     */
    @GetMapping("/current-user")
    @PreAuthorize("hasAnyAuthority('ADMIN','USER')")
    @Operation(summary = "查询当前用户的所有投诉")
    public HttpResult<List<ComplainResponseDTO>> getCurrentUserComplains() {
        try {
            User currentUser = userService.getUserWithAuthorities()
                    .orElseThrow(() -> new IllegalStateException("无法获取当前用户信息"));

            List<Complain> complains = complainService.getComplainsByCustomerId(currentUser.getId());
            List<ComplainResponseDTO> responseDTOs = complainMapper.complainsToResponseDTOs(complains);

            return HttpResult.success(responseDTOs);
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "查询失败：" + e.getMessage());
        }
    }

    /**
     * 根据用户ID查询投诉列表
     */
    @GetMapping("/user/{userId}")
    @PreAuthorize("hasAuthority('ADMIN') or @permissionUtils.canAccessUserData(#userId)")
    @Operation(summary = "根据用户ID查询投诉列表", description = "管理员或用户本人可查看")
    public HttpResult<List<ComplainResponseDTO>> getComplainsByUserId(@PathVariable Long userId) {
        List<Complain> complains = complainService.getComplainsByCustomerId(userId);
        List<ComplainResponseDTO> responseDTOs = complainMapper.complainsToResponseDTOs(complains);
        return HttpResult.success(responseDTOs);
    }

    /**
     * 根据商家ID查询投诉列表
     */
    @GetMapping("/business/{businessId}")
    @PreAuthorize("hasAnyAuthority('ADMIN','BUSINESS')")
    @Operation(summary = "根据商家ID查询投诉列表", description = "管理员或商家本人可查看")
    public HttpResult<List<ComplainResponseDTO>> getComplainsByBusinessId(@PathVariable Long businessId) {
        // 权限检查：管理员可以访问所有，商家只能访问自己的
        if (!permissionUtils.isAdmin()) {
            Optional<Business> business = businessService.getBusinessById(businessId);
            if (business.isEmpty() || !permissionUtils.canAccessBusinessData(business.get().getBusinessOwner().getId())) {
                return HttpResult.failure(ResultCodeEnum.BAD_REQUEST, "无权访问此商家的投诉信息");
            }
        }
        
        List<Complain> complains = complainService.getComplainsByBusinessId(businessId);
        List<ComplainResponseDTO> responseDTOs = complainMapper.complainsToResponseDTOs(complains);
        return HttpResult.success(responseDTOs);
    }

    /**
     * 查询所有投诉（管理员）
     */
    @GetMapping("/all")
    @PreAuthorize("hasAuthority('ADMIN')")
    @Operation(summary = "查询所有投诉", description = "仅管理员可访问")
    public HttpResult<List<ComplainResponseDTO>> getAllComplains() {
        List<Complain> complains = complainService.getAllComplains();
        List<ComplainResponseDTO> responseDTOs = complainMapper.complainsToResponseDTOs(complains);
        return HttpResult.success(responseDTOs);
    }

    /**
     * 根据状态查询投诉列表（管理员）
     */
    @GetMapping("/state/{state}")
    @PreAuthorize("hasAuthority('ADMIN')")
    @Operation(summary = "根据状态查询投诉", description = "状态：0-待审核，1-商家已拒绝，2-已通过，3-管理员已拒绝")
    public HttpResult<List<ComplainResponseDTO>> getComplainsByState(@PathVariable Integer state) {
        if (state < 0 || state > 3) {
            return HttpResult.failure(ResultCodeEnum.BAD_REQUEST, "无效的状态值");
        }
        List<Complain> complains = complainService.getComplainsByState(state);
        List<ComplainResponseDTO> responseDTOs = complainMapper.complainsToResponseDTOs(complains);
        return HttpResult.success(responseDTOs);
    }

    /**
     * 商家同意投诉
     */
    @PatchMapping("/{id}/business-approve")
    @PreAuthorize("hasAuthority('ADMIN') or (hasAuthority('BUSINESS') and @permissionUtils.canAccessBusinessData(@complainService.getComplainById(#id).get().getBusiness().getBusinessOwner().getId()))")
    @Operation(summary = "商家同意投诉", description = "商家只能处理自己店铺的投诉")
    public HttpResult<ComplainResponseDTO> businessApproveComplain(
            @PathVariable Long id,
            @RequestBody Map<String, String> requestBody) {
        try {
            String reply = requestBody.getOrDefault("reply", "商家已同意该投诉");
            Complain updatedComplain = complainService.businessHandleComplain(id, 2, reply);
            ComplainResponseDTO responseDTO = complainMapper.complainToResponseDTO(updatedComplain);
            return HttpResult.success(responseDTO);
        } catch (IllegalStateException | IllegalArgumentException e) {
            return HttpResult.failure(ResultCodeEnum.BAD_REQUEST, e.getMessage());
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "处理失败：" + e.getMessage());
        }
    }

    /**
     * 商家拒绝投诉
     */
    @PatchMapping("/{id}/business-reject")
    @PreAuthorize("hasAuthority('ADMIN') or (hasAuthority('BUSINESS') and @permissionUtils.canAccessBusinessData(@complainService.getComplainById(#id).get().getBusiness().getBusinessOwner().getId()))")
    @Operation(summary = "商家拒绝投诉", description = "商家只能处理自己店铺的投诉")
    public HttpResult<ComplainResponseDTO> businessRejectComplain(
            @PathVariable Long id,
            @RequestBody Map<String, String> requestBody) {
        try {
            String reply = requestBody.getOrDefault("reply", "商家已拒绝该投诉");
            Complain updatedComplain = complainService.businessHandleComplain(id, 1, reply);
            ComplainResponseDTO responseDTO = complainMapper.complainToResponseDTO(updatedComplain);
            return HttpResult.success(responseDTO);
        } catch (IllegalStateException | IllegalArgumentException e) {
            return HttpResult.failure(ResultCodeEnum.BAD_REQUEST, e.getMessage());
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "处理失败：" + e.getMessage());
        }
    }

    /**
     * 管理员同意投诉
     */
    @PatchMapping("/{id}/admin-approve")
    @PreAuthorize("hasAuthority('ADMIN')")
    @Operation(summary = "管理员同意投诉", description = "仅管理员可访问")
    public HttpResult<ComplainResponseDTO> adminApproveComplain(
            @PathVariable Long id,
            @RequestBody Map<String, String> requestBody) {
        try {
            String reply = requestBody.getOrDefault("reply", "管理员已同意该投诉");
            Complain updatedComplain = complainService.adminHandleComplain(id, 2, reply);
            ComplainResponseDTO responseDTO = complainMapper.complainToResponseDTO(updatedComplain);
            return HttpResult.success(responseDTO);
        } catch (IllegalStateException | IllegalArgumentException e) {
            return HttpResult.failure(ResultCodeEnum.BAD_REQUEST, e.getMessage());
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "处理失败：" + e.getMessage());
        }
    }

    /**
     * 管理员拒绝投诉
     */
    @PatchMapping("/{id}/admin-reject")
    @PreAuthorize("hasAuthority('ADMIN')")
    @Operation(summary = "管理员拒绝投诉", description = "仅管理员可访问")
    public HttpResult<ComplainResponseDTO> adminRejectComplain(
            @PathVariable Long id,
            @RequestBody Map<String, String> requestBody) {
        try {
            String reply = requestBody.getOrDefault("reply", "管理员已拒绝该投诉");
            Complain updatedComplain = complainService.adminHandleComplain(id, 3, reply);
            ComplainResponseDTO responseDTO = complainMapper.complainToResponseDTO(updatedComplain);
            return HttpResult.success(responseDTO);
        } catch (IllegalStateException | IllegalArgumentException e) {
            return HttpResult.failure(ResultCodeEnum.BAD_REQUEST, e.getMessage());
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "处理失败：" + e.getMessage());
        }
    }

    /**
     * 删除投诉（软删除）
     */
    @DeleteMapping("/{id}")
    @PreAuthorize("hasAuthority('ADMIN') or @permissionUtils.canAccessComplainData(@complainService.getComplainById(#id).get().getCustomer().getId())")
    @Operation(summary = "删除投诉", description = "用户只能删除自己的投诉，管理员可以删除所有投诉")
    public HttpResult<String> deleteComplain(@PathVariable Long id) {
        try {
            complainService.deleteComplain(id);
            return HttpResult.success("投诉删除成功");
        } catch (Exception e) {
            return HttpResult.failure(ResultCodeEnum.SERVER_ERROR, "删除失败：" + e.getMessage());
        }
    }

    /**
     * 获取商家投诉统计
     */
    @GetMapping("/business/{businessId}/statistics")
    @PreAuthorize("hasAnyAuthority('ADMIN','BUSINESS')")
    @Operation(summary = "获取商家投诉统计", description = "管理员或商家本人可查看")
    public HttpResult<Map<String, Object>> getBusinessComplainStatistics(@PathVariable Long businessId) {
        // 权限检查：管理员可以访问所有，商家只能访问自己的
        if (!permissionUtils.isAdmin()) {
            Optional<Business> business = businessService.getBusinessById(businessId);
            if (business.isEmpty() || !permissionUtils.canAccessBusinessData(business.get().getBusinessOwner().getId())) {
                return HttpResult.failure(ResultCodeEnum.BAD_REQUEST, "无权访问此商家的投诉统计信息");
            }
        }
        
        Long totalCount = complainService.countByBusinessId(businessId);
        Long pendingCount = complainService.countPendingByBusinessId(businessId);

        Map<String, Object> statistics = Map.of(
                "totalComplains", totalCount,
                "pendingComplains", pendingCount,
                "handledComplains", totalCount - pendingCount
        );

        return HttpResult.success(statistics);
    }
}

